package xcmg.device.service.abnormal;

import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.abnormal.AbnormalOutDO;
import xcmg.device.dao.entity.abnormal.AbnormalOutDetailDO;
import xcmg.device.dao.entity.abnormal.AbnormalOutExportDO;
import xcmg.device.dao.entity.delivery.DeliveryReceiptMaterialDO;
import xcmg.device.dao.entity.split.SplitDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDetailDO;
import xcmg.device.dao.mapper.MaterialLocationRelationMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.abnormal.AbnormalOutDetailMapper;
import xcmg.device.dao.mapper.abnormal.AbnormalOutMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptLinkMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptMaterialMapper;
import xcmg.device.dao.mapper.split.SplitMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseAreaLocationDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.ImportUtil;
import xcmg.device.infra.enums.AbnormalOutAuditStatusEnum;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.basic.SystemParameterService;
import xcmg.device.service.delivery.DeliveryReceiptMaterialService;
import xcmg.device.service.split.SplitService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.abnormal.AbnormalAddVO;
import xcmg.device.service.vo.abnormal.AbnormalOutDetailVO;
import xcmg.device.service.vo.abnormal.AbnormalOutVO;
import xcmg.device.service.vo.basic.MaterialLocationRelationVO;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptMaterialVO;
import xcmg.device.service.vo.permission.WareHousePermission;
import xcmg.device.service.vo.warehouse.BillTypeConfigVO;
import xcmg.device.service.vo.warehouse.FindMaterialsInfos;
import xcmg.device.service.vo.warehouse.FindMaterialsNumParam;
import xcmg.device.service.vo.warehouse.app.EnableAndOccupyVO;
import xcmg.device.service.vo.warehouse.sap.ObligateVO;
import xcmg.device.service.warehouse.BillTypeConfigService;
import xcmg.device.service.warehouse.DepartmentWarehouseRelationService;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.util.DecimalUtil;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class AbnormalOutService {
    @Autowired
    private SystemParameterService systemParameterService;

    @Autowired
    private AbnormalOutMapper abnormalOutMapper;

    @Autowired
    private WarehouseDOMapper warehouseDOMapper;

    @Autowired
    private AbnormalOutDetailMapper abnormalOutDetailMapper;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private WarehouseDeliveryMapper warehouseDeliveryMapper;

    @Autowired
    private WarehouseDeliveryDetailMapper warehouseDeliveryDetailMapper;

    @Autowired
    private MaterialsService materialsService;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private BillTypeConfigService billTypeConfigService;

    @Autowired
    private MaterialLocationRelationMapper materialLocationRelationMapper;

    @Autowired
    private WarehouseInventoryService warehouseInventoryService;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private SplitService splitService;

    @Autowired
    private SplitMapper splitMapper;

    @Autowired
    private PriMaterialsMapper priMaterialsMapper;

    @Autowired
    private DeliveryReceiptLinkMapper deliveryReceiptLinkMapper;

    @Autowired
    private DeliveryReceiptMaterialService deliveryReceiptMaterialService;

    @Autowired
    private DeliveryReceiptMaterialMapper deliveryReceiptMaterialMapper;
    @Autowired
    private DepartmentWarehouseRelationService relationService;
    @Autowired
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;
    @Value("${spring.file.download.path}")
    private String filePath;
    private String templateExcelFileName = "UnNormalOutImport.xls";

    /**
     * 出库状态：手动完成
     */
    private static final Integer OUT_STATUS_FINISH = 3;

    /**
     * 过账状态。2已过账
     */
    private static final Integer POST_STATUS_YES = 2;

    public PageCommonVO list(SearchCommonVO<AbnormalOutVO> condition,String deptId) {
        PageCommonVO result = new PageCommonVO();

        // 判断当前登陆的用户所属组织机构是否有配置仓库，如果开启了仓库控制并配置了仓库，则需要把配置的仓库加入到查询的限制条件
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(condition.getFilters().getOrgId(), deptId);
        if (!wareHousePermission.isHasPermission()) {
            result.setPageInfo(new PageInfo(new ArrayList()));
            result.setPageInfoList(new ArrayList<>());
            return result;
        } else {
            condition.getFilters().setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }
        PageHelperPlus.orderBy("application_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<AbnormalOutDO> doList = abnormalOutMapper.list(condition.getFilters());
        List<AbnormalOutVO> voList = new ArrayList<>();
        for (AbnormalOutDO entity : doList) {
            AbnormalOutVO model = new AbnormalOutVO();
            if (entity.getTotalAmount() != null) {
                entity.setTotalAmount(entity.getTotalAmount().divide(new BigDecimal("100")));
            }
            if (entity.getCostTotal() != null) {
                entity.setCostTotal(entity.getCostTotal().divide(new BigDecimal("100")));
            }
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    /**
     * 备件系统手动添加调用
     *
     * @param abnormalAddVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized ErrorCode save(AbnormalAddVO abnormalAddVO) throws Exception {
        return ErrorCode.getByCode(add(abnormalAddVO).getCode());
    }

    /**
     * CRM调用
     *
     * @param abnormalAddVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized ActionResult save4CRM(AbnormalAddVO abnormalAddVO) throws Exception {
        return add(abnormalAddVO);
    }

    private ActionResult add(AbnormalAddVO abnormalAddVO) throws Exception {
        ActionResult actionResult = new ActionResult();
        AbnormalOutDO abnormalOutDO = new AbnormalOutDO();
        BeanUtils.copyProperties(abnormalAddVO.getHeaderInfo(), abnormalOutDO);
        ActionResult<Long> result = fastGenClient.numberGuid();
        if (result == null || result.getCode() != 0) {
            actionResult.setCode(ErrorCode.Failure.getCode());
            return actionResult;
        }
        if (!StringUtil.isNullOrEmpty(abnormalOutDO.getSplitOrder())) {
            SplitDO splitDO = splitMapper.selectBySplitOrder(abnormalOutDO.getSplitOrder(), abnormalOutDO.getOrgId());
            if (splitDO == null) {
                actionResult.setCode(ErrorCode.splitNotExist.getCode());
                return actionResult;
            }
        }
        abnormalOutDO.setId(result.getValue().toString());
        abnormalOutDO.setAbnormalNo(genDocumentService.genDocumentNo(BillDesc.AbnormalOutNo, abnormalOutDO.getOrgId()));
        abnormalOutDO.setApplicationDate(new Date());
        abnormalOutDO.setStatus(0);

        BillTypeConfigVO config = billTypeConfigService.findByPK(abnormalOutDO.getTypeId());
        if (config != null) {
            abnormalOutDO.setIsSynsap(new BigDecimal(config.getIsSynsap()));
            abnormalOutDO.setType(config.getType());
            abnormalOutDO.setMoveType(config.getMoveType());
        } else {
            abnormalOutDO.setIsSynsap(BigDecimal.ZERO);
        }
        List<FindMaterialsInfos> infos=new ArrayList<>();
        for (AbnormalOutDetailVO detailVO : abnormalAddVO.getMaterialList()) {
            FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
            findMaterialsInfos.setMaterialsNo(detailVO.getMaterialsNo());
            findMaterialsInfos.setAmount(detailVO.getQty());
            infos.add(findMaterialsInfos);
        }
        FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
        findMaterialsNumParam.setMaterialsNos(infos);
        findMaterialsNumParam.setOrgId(abnormalOutDO.getOrgId());
        findMaterialsNumParam.setWarehousCode(abnormalOutDO.getOutLocation());
        if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
            actionResult.setCode(ErrorCode.PartMaterialsNotNumber.getCode());
            return actionResult;
        }

        List<ObligateVO> obligateVOList = new ArrayList<>();
        ObligateVO obligateVO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal costTotal = BigDecimal.ZERO;
        for (AbnormalOutDetailVO detailVO : abnormalAddVO.getMaterialList()) {
            AbnormalOutDetailDO detailDO = new AbnormalOutDetailDO();
            BeanUtils.copyProperties(detailVO, detailDO);
            ActionResult<String> textOutDetail = fastGenClient.textGuid();
            if (textOutDetail.getCode() != ErrorCode.Success.getCode()) {
                actionResult.setCode(ErrorCode.IllegalArument.getCode());
                return actionResult;
            }
            detailDO.setId(textOutDetail.getValue());
            detailDO.setOrgId(abnormalOutDO.getOrgId());
            detailDO.setAbnormalNo(abnormalOutDO.getAbnormalNo());
            detailDO.setStatus(0);
            detailDO.setRealQty(BigDecimal.ZERO);

            BigDecimal price = DecimalUtil.roundDecimal4Enter(detailVO.getPrice());
            BigDecimal totalPrice = price.multiply(detailVO.getQty());
            totalAmount = totalAmount.add(totalPrice);

            BigDecimal costPrice = DecimalUtil.roundDecimal4Enter(detailVO.getCostPrice());
            BigDecimal costSubtotal = costPrice.multiply(detailVO.getQty());
            costTotal = costTotal.add(costSubtotal);

            detailDO.setPrice(price);
            detailDO.setTotalPrice(totalPrice);
            detailDO.setCostPrice(costPrice);
            detailDO.setCostSubtotal(costSubtotal);
            abnormalOutDetailMapper.add(detailDO);

            //判断是否需要同步到sap创建预留单
            if (abnormalOutDO.getIsSynsap().intValue() == 1) {
                obligateVO = new ObligateVO();
                obligateVO.setMaterialNo(detailVO.getMaterialsNo());
                obligateVO.setAmount(detailVO.getQty());
                obligateVO.setInnerOrder(abnormalOutDO.getInnerOrder());
                obligateVO.setMoveType(abnormalOutDO.getMoveType());
                obligateVO.setWarehouseCode(abnormalOutDO.getOutLocation());
                obligateVO.setSapOutArea(abnormalAddVO.getHeaderInfo().getSapOutArea());
                obligateVO.setGeneralLedgerCategory(abnormalOutDO.getGeneralLedgerCategory());
                obligateVOList.add(obligateVO);
            }
        }

        abnormalOutDO.setTotalAmount(totalAmount);
        abnormalOutDO.setCostTotal(costTotal);
        //设置单据的初始化审核状态
        saveAbnormalOutInitAudit(abnormalOutDO);
        abnormalOutMapper.add(abnormalOutDO);

//        //判断是否需要同步到sap创建预留单
//        boolean sapNoPostOrg = sapCommonService.sapNoPostOrg(abnormalOutDO.getOrgId());
//        if (abnormalOutDO.getIsSynsap().intValue() == 1 && !sapNoPostOrg) {
//            ObligateHeaderVO headerVO = new ObligateHeaderVO();
//            headerVO.setBusinesId(abnormalOutDO.getId());
//            headerVO.setBusinesOrder(abnormalOutDO.getAbnormalNo());
//            headerVO.setBusinesSingle(abnormalOutDO.getAbnormalNo().substring(0, 4));
//            sapCommonService.createObligateOrder(headerVO, obligateVOList, null, abnormalOutDO.getOrgId());
//        }

        //非正常出库添加到出库单
        WarehouseDeliveryDO warehouseDeliveryDO = new WarehouseDeliveryDO();
        ActionResult<String> textDelivery = fastGenClient.textGuid();
        if (textDelivery.getCode() != ErrorCode.Success.getCode()) {
            actionResult.setCode(ErrorCode.IllegalArument.getCode());
            return actionResult;
        }
        //主键
        warehouseDeliveryDO.setId(textDelivery.getValue().toString());
        //出库单号
        warehouseDeliveryDO.setDeliveryOrder(genDocumentService.genDocumentNo(BillDesc.OutputNo, abnormalOutDO.getOrgId()));
        //业务单号（非正常出库单号）
        warehouseDeliveryDO.setBusinessOrder(abnormalOutDO.getAbnormalNo());
        //业务单别（非正常出库单单别）
        warehouseDeliveryDO.setBusinessSingle(BillDesc.AbnormalOutNo.getDesc());
        //备注
        warehouseDeliveryDO.setNote(abnormalOutDO.getNote());
        //创建人
        warehouseDeliveryDO.setCreaterId(abnormalAddVO.getHeaderInfo().getCreateId());
        warehouseDeliveryDO.setCreaterName(abnormalAddVO.getHeaderInfo().getCreateName());
        //状态
        warehouseDeliveryDO.setStatus(0);
        //创建时间
        warehouseDeliveryDO.setCreateDate(new Date());
        warehouseDeliveryDO.setOrgId(abnormalOutDO.getOrgId());
        warehouseDeliveryDO.setWarehouseCode(abnormalOutDO.getOutLocation());
        warehouseDeliveryDO.setOutArea(abnormalOutDO.getOutArea());
        warehouseDeliveryDO.setSapOutArea(abnormalOutDO.getSapOutArea());
        warehouseDeliveryDO.setNote(abnormalOutDO.getNote());
        warehouseDeliveryDO.setSplitOrder(abnormalOutDO.getSplitOrder());
        for (AbnormalOutDetailVO abnormalOutDetailVO : abnormalAddVO.getMaterialList()) {
            WarehouseDeliveryDetailDO warehouseDeliveryDetailDO = new WarehouseDeliveryDetailDO();
            ActionResult<String> textDeliveryDetail = fastGenClient.textGuid();
            if (textDeliveryDetail.getCode() != ErrorCode.Success.getCode()) {
                actionResult.setCode(ErrorCode.IllegalArument.getCode());
                return actionResult;
            }
            warehouseDeliveryDetailDO.setId(textDeliveryDetail.getValue().toString());
            warehouseDeliveryDetailDO.setDeliveryOrder(warehouseDeliveryDO.getDeliveryOrder());
            warehouseDeliveryDetailDO.setBusinessSingle(BillDesc.AbnormalOutNo.getDesc());
            warehouseDeliveryDetailDO.setBusinessOrder(abnormalOutDO.getAbnormalNo());
            warehouseDeliveryDetailDO.setMaterialNo(abnormalOutDetailVO.getMaterialsNo());
            warehouseDeliveryDetailDO.setMaterialType(abnormalOutDetailVO.getMaterialsType());
            warehouseDeliveryDetailDO.setRealAmount(abnormalOutDetailVO.getRealQty());
            warehouseDeliveryDetailDO.setAmount(abnormalOutDetailVO.getQty());
            warehouseDeliveryDetailDO.setUnit(abnormalOutDetailVO.getUnit());
            warehouseDeliveryDetailDO.setCreaterId(abnormalAddVO.getHeaderInfo().getCreateId());
            warehouseDeliveryDetailDO.setCreaterName(abnormalAddVO.getHeaderInfo().getCreateName());
            warehouseDeliveryDetailDO.setCreateDate(new Date());
            warehouseDeliveryDetailDO.setMaterialName(abnormalOutDetailVO.getMaterialsDes());
            warehouseDeliveryDetailDO.setStatus(0);
            warehouseDeliveryDetailDO.setOrgId(abnormalOutDO.getOrgId());
            warehouseDeliveryDetailMapper.insert(warehouseDeliveryDetailDO);
        }
        warehouseDeliveryMapper.insert(warehouseDeliveryDO);
        actionResult.setCode(ErrorCode.Success.getCode());
        actionResult.setValue(abnormalOutDO.getAbnormalNo());
        return actionResult;
    }

    private void saveAbnormalOutInitAudit(AbnormalOutDO abnormal){
        if(abnormal == null){
            return ;
        }
        boolean abnormalOutAuditSetting = systemParameterService.getAbnormalOutAuditSetting(abnormal.getOrgId());
        if(abnormalOutAuditSetting){//需要走审核流程
            abnormal.setAuditStatus(AbnormalOutAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
        }else{//不需要走审核流程
            abnormal.setAuditStatus(AbnormalOutAuditStatusEnum.AUDIT_PASS.getAuditStatus());
            abnormal.setAuditDate(new Date());
            abnormal.setAuditRemark(null);
            abnormal.setAuditUserId("0001");
            abnormal.setAuditUserName("系统自动");
        }
    }

    public ErrorCode remove(List<String> ids, String orgId) {
        List<AbnormalOutDO> list = abnormalOutMapper.findForDeleteByIds(ids);
        if (!ListUtil.isNullOrEmpty(list)) {
            return ErrorCode.AbnormalOutDeleteError;
        }
        List<DeliveryReceiptMaterialVO> receiptMaterialList = new ArrayList<>();
        Set<String> receIds = new HashSet<>();
        List<AbnormalOutDO> dataList = abnormalOutMapper.findOrderList(ids);
        List<String> orderList = new ArrayList<>();
        for (AbnormalOutDO outDO : dataList) {
            orderList.add(outDO.getAbnormalNo());
        }
        for (AbnormalOutDO outDO : dataList) {
            List<String> receiptIds = deliveryReceiptLinkMapper.findReceiptIds(outDO.getId());
            receIds.addAll(receiptIds);
            List<AbnormalOutDetailDO> detailDOList = abnormalOutDetailMapper.list(outDO.getAbnormalNo());
            if (!ListUtil.isNullOrEmpty(receiptIds)) {
                for (AbnormalOutDetailDO outDetailDO : detailDOList) {
                    for (String receiptId : receiptIds) {
                        DeliveryReceiptMaterialVO receiptMaterialDO = new DeliveryReceiptMaterialVO();
                        receiptMaterialDO.setDeliveryReceiptId(receiptId);
                        receiptMaterialDO.setMaterialsNo(outDetailDO.getMaterialsNo());
                        receiptMaterialDO.setQty(outDetailDO.getQty());
                        receiptMaterialDO.setUpdateType(0);
                        receiptMaterialList.add(receiptMaterialDO);
                    }
                }

                for (String receiptId : receiptIds) {
                    deliveryReceiptLinkMapper.deleteItem(receiptId, outDO.getId());
                }
            }
        }

        boolean success = abnormalOutMapper.remove(ids) > 0;
        //删除入库详情记录
        if (success && CollectionUtils.isNotEmpty(orderList)) {
            abnormalOutDetailMapper.removeByInOrderList(orderList, orgId);

            //删除事物单
            warehouseDeliveryService.removeByBusinessOrders(orderList, orgId);
        }

        //更新发运交接单
        deliveryReceiptMaterialService.updateByAdjust(new ArrayList<>(receIds), receiptMaterialList);

        return success ? ErrorCode.Success : ErrorCode.WarehouseIdError;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(AbnormalAddVO abnormalOutAddVO, String orgId) throws Exception {
        AbnormalOutVO abnormalOutVO = abnormalOutAddVO.getHeaderInfo();
        List<AbnormalOutDetailVO> detailList = abnormalOutAddVO.getMaterialList();
        if (!StringUtil.isNullOrEmpty(abnormalOutVO.getSplitOrder())) {
            SplitDO splitDO = splitMapper.selectBySplitOrder(abnormalOutVO.getSplitOrder(), abnormalOutVO.getOrgId());
            if (splitDO == null) {
                return ErrorCode.splitNotExist;
            }
        }
        boolean allComplete = true;
        boolean someComplete = false;
        boolean manulComplete = false;
        boolean success;
        List<FindMaterialsInfos> infos=new ArrayList<>();
        for (AbnormalOutDetailVO vo : detailList) {
            if (vo.getQty().compareTo(vo.getRealQty()) < 0) {  //出库数量必须大于等于实际出库数量
                return ErrorCode.OutboundNumError;
            }
            if(vo.getStatus()<=1){
                FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                findMaterialsInfos.setMaterialsNo(vo.getMaterialsNo());
                findMaterialsInfos.setAmount(vo.getQty().subtract(vo.getRealQty()));
                infos.add(findMaterialsInfos);
            }
        }
        FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
        findMaterialsNumParam.setMaterialsNos(infos);
        findMaterialsNumParam.setOrgId(orgId);
        findMaterialsNumParam.setBusinessOrder(abnormalOutAddVO.getHeaderInfo().getAbnormalNo());
        findMaterialsNumParam.setWarehousCode(abnormalOutAddVO.getHeaderInfo().getOutLocation());
        if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
            return ErrorCode.PartMaterialsNotNumber;
        }
        AbnormalOutDetailDO detailDO = null;
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal costTotal = BigDecimal.ZERO;
        List<String> receiptIds = deliveryReceiptLinkMapper.findReceiptIds(abnormalOutVO.getId());
        List<DeliveryReceiptMaterialVO> receiptMaterialVOList = new ArrayList<>();
        for (AbnormalOutDetailVO vo : detailList) {
            detailDO = new AbnormalOutDetailDO();
            AbnormalOutDetailDO abnormalOutDetailDO = abnormalOutDetailMapper.selectByPrimaryKey(vo.getId());
            if (abnormalOutDetailDO.getStatus() == 3) {
                manulComplete = true;
            }
            if (abnormalOutDetailDO.getStatus() == 2 || abnormalOutDetailDO.getStatus() == 3) {
                someComplete = true;
                continue;
            }
            if (vo.getQty().compareTo(vo.getRealQty()) > 0) {
                if (allComplete) {
                    allComplete = false;
                }
                if (vo.getRealQty().compareTo(BigDecimal.ZERO) == 0) {
                    detailDO.setStatus(0);
                } else {
                    detailDO.setStatus(1);
                    someComplete = true;
                }
            } else {
                someComplete = true;
                detailDO.setStatus(2);
            }

            //更新出库事物单详情记录
            ErrorCode errorCode = warehouseDeliveryService.updateDetailState(abnormalOutVO.getAbnormalNo(),
                    vo.getMaterialsNo(), vo.getQty(), detailDO.getStatus(), orgId);
            if (errorCode.getCode() != 0) {
                throw new Exception("更新出库事物单详情记录失败");
            }

            detailDO.setId(vo.getId());
            detailDO.setQty(vo.getQty());
            detailDO.setRealQty(vo.getRealQty());

            BigDecimal price = DecimalUtil.roundDecimal4Enter(vo.getPrice());
            BigDecimal totalPrice = price.multiply(vo.getQty());
            totalAmount = totalAmount.add(totalPrice);
            detailDO.setPrice(price);
            detailDO.setTotalPrice(totalPrice);

            BigDecimal costPrice = DecimalUtil.roundDecimal4Enter(vo.getCostPrice());
            BigDecimal costSubtotal = costPrice.multiply(vo.getQty());
            costTotal = costTotal.add(costSubtotal);
            detailDO.setCostPrice(costPrice);
            detailDO.setCostSubtotal(costSubtotal);

            success = abnormalOutDetailMapper.updateByPrimaryKeySelective(detailDO) > 0;
            if (!success) {
                throw new Exception("更新详情记录失败");
            }

            for (String receiptId : receiptIds) {
                DeliveryReceiptMaterialVO receiptMaterialVO = new DeliveryReceiptMaterialVO();
                receiptMaterialVO.setMaterialsNo(abnormalOutDetailDO.getMaterialsNo());
                receiptMaterialVO.setOldQty(abnormalOutDetailDO.getQty());
                receiptMaterialVO.setQty(detailDO.getQty());
                receiptMaterialVO.setDeliveryReceiptId(receiptId);
                receiptMaterialVO.setUpdateType(1);
                receiptMaterialVOList.add(receiptMaterialVO);
            }
        }
        AbnormalOutDO abnormalOutDO = new AbnormalOutDO();
        BeanUtils.copyProperties(abnormalOutVO, abnormalOutDO);
        if (allComplete) {
            if (manulComplete) {
                abnormalOutDO.setStatus(3);
            } else {
                abnormalOutDO.setStatus(2);
            }
        } else if (someComplete) {
            abnormalOutDO.setStatus(1);
        } else {
            abnormalOutDO.setStatus(0);
        }
        BillTypeConfigVO config = billTypeConfigService.findByPK(abnormalOutDO.getTypeId());
        if (config != null) {
            abnormalOutDO.setIsSynsap(new BigDecimal(config.getIsSynsap()));
            abnormalOutDO.setType(config.getType());
            abnormalOutDO.setMoveType(config.getMoveType());
        }
        abnormalOutDO.setTotalAmount(totalAmount);
        abnormalOutDO.setCostTotal(costTotal);
        //更新操作的时候需要重置单据的审核状态
        resetAuditInfo(orgId,abnormalOutDO);
        success = abnormalOutMapper.update4Edit(abnormalOutDO) > 0;
        if (!success) {
            throw new Exception("更新失败");
        }

        //更新出库事务单
        ErrorCode errorCode = warehouseDeliveryService.updateState(abnormalOutVO.getAbnormalNo(), abnormalOutDO.getStatus(), orgId);
        if (errorCode.getCode() != 0) {
            throw new Exception("更新出库事务单记录失败");
        }

        //更新发运交接单
        deliveryReceiptMaterialService.updateByAdjust(receiptIds, receiptMaterialVOList);

        return errorCode;
    }

    private void resetAuditInfo(String orgId, AbnormalOutDO updateAbnormalOut) throws Exception {
        if(updateAbnormalOut == null){
            throw new Exception("未找到出库单据");
        }
        String id = updateAbnormalOut.getId();
        AbnormalOutDO oldAbnormalOut = abnormalOutMapper.selectByPrimaryKey(id);
        if(oldAbnormalOut == null){
            throw new Exception("未找到出库单据");
        }
        // 如果审核已经通过了，再调整的时候审核状态不修改
        Integer oldAuditStatus = oldAbnormalOut.getAuditStatus();
        //判断操作公司的是否配置未需要审核，如果需要审核且单据审核状态为拒绝状态的则需要更新单据的审核状态为待审核状态，否则维持原有值不变
        boolean deliveryNoteAuditSetting = systemParameterService.getDeliveryNoteAuditSetting(orgId);
        if(deliveryNoteAuditSetting
                && oldAuditStatus != null
                && oldAuditStatus.compareTo(AbnormalOutAuditStatusEnum.AUDIT_REJECT.getAuditStatus()) == 0){
            updateAbnormalOut.setAuditStatus(AbnormalOutAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
            updateAbnormalOut.setAuditUserName(null);
            updateAbnormalOut.setAuditUserId(null);
            updateAbnormalOut.setAuditRemark(null);
            updateAbnormalOut.setAuditDate(null);
        }else{
            updateAbnormalOut.setAuditStatus(oldAbnormalOut.getAuditStatus());
            updateAbnormalOut.setAuditUserName(oldAbnormalOut.getAuditUserName());
            updateAbnormalOut.setAuditUserId(oldAbnormalOut.getAuditUserId());
            updateAbnormalOut.setAuditRemark(oldAbnormalOut.getAuditRemark());
            updateAbnormalOut.setAuditDate(oldAbnormalOut.getAuditDate());
        }
    }

    public AbnormalAddVO item(String AbnormalNo) {
        AbnormalAddVO result = new AbnormalAddVO();
        AbnormalOutDO abnormalOutDO = abnormalOutMapper.item(AbnormalNo);
        AbnormalOutVO abnormalOutVO = new AbnormalOutVO();
        if (abnormalOutDO == null) {
            return result;
        }
        if (abnormalOutDO.getTotalAmount() != null) {
            abnormalOutDO.setTotalAmount(abnormalOutDO.getTotalAmount().divide(new BigDecimal("100")));
        }
        if (abnormalOutDO.getCostTotal() != null) {
            abnormalOutDO.setCostTotal(abnormalOutDO.getCostTotal().divide(new BigDecimal("100")));
        }
        BeanUtils.copyProperties(abnormalOutDO, abnormalOutVO);
        if (StringUtils.isNotBlank(abnormalOutVO.getOutLocation())) {
            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(abnormalOutDO.getOrgId(), abnormalOutVO.getOutLocation());
            if (null != warehouse) {
                abnormalOutVO.setWarehouseCodeDesc(warehouse.getDescription());
            }
        }
        result.setHeaderInfo(abnormalOutVO);
        List<AbnormalOutDetailVO> listVO = new ArrayList<>();
        List<AbnormalOutDetailDO> listDO = abnormalOutDetailMapper.listForLocationUser(abnormalOutDO.getAbnormalNo());
        EnableAndOccupyVO enableAndOccupyVO;
        for (AbnormalOutDetailDO entity : listDO) {
            AbnormalOutDetailVO model = new AbnormalOutDetailVO();
            if (entity.getPrice() != null) {
                entity.setPrice(entity.getPrice().divide(new BigDecimal("100")));
            }
            if (entity.getTotalPrice() != null) {
                entity.setTotalPrice(entity.getTotalPrice().divide(new BigDecimal("100")));
            }

            if (entity.getCostPrice() != null) {
                entity.setCostPrice(entity.getCostPrice().divide(new BigDecimal("100")));
            }
            if (entity.getCostSubtotal() != null) {
                entity.setCostSubtotal(entity.getCostSubtotal().divide(new BigDecimal("100")));
            }

            BeanUtils.copyProperties(entity, model);

            //获取库存储位
            getDefaultLocationCode(abnormalOutDO.getOrgId(), abnormalOutDO.getOutLocation(), model,abnormalOutDO.getOutArea());

            enableAndOccupyVO = warehouseInventoryService.findEnableAndOccupyNum(entity.getMaterialsNo(), abnormalOutVO.getOrgId(), abnormalOutDO.getOutLocation());
            BeanUtils.copyProperties(enableAndOccupyVO, model);
            listVO.add(model);
        }

        Collections.sort(listVO, new Comparator<AbnormalOutDetailVO>() {
            @Override
            public int compare(AbnormalOutDetailVO o1, AbnormalOutDetailVO o2) {
                if (o1.getLocationCode()==null && o2.getLocationCode()==null){
                    return 0;
                }else if (o1.getLocationCode()==null){
                    return -1;
                }else if (o2.getLocationCode()==null){
                    return 1;
                }else {
                    return o1.getLocationCode().compareTo(o2.getLocationCode());
                }
            }
        });
        result.setMaterialList(listVO);
        return result;
    }

    // 获取库存储位
    private void getDefaultLocationCode(String orgId, String warehouseCode, AbnormalOutDetailVO model,String outArea) {
        //MaterialLocationRelationVO condition = new MaterialLocationRelationVO();
        //condition.setWarehouseCode(warehouseCode);
        //condition.setOrgId(orgId);
        //condition.setMaterialNo(model.getMaterialsNo());
        //List<MaterialLocationRelationVO> voList = materialLocationRelationMapper.list(condition);
        List<String> locationCodeList = warehouseInventoryMapper.findLocationCode(orgId, model.getMaterialsNo(), warehouseCode, outArea);
        if (locationCodeList.isEmpty()) {
            return;
        }
        model.setLocationCode(String.join(",",locationCodeList));

        if (!locationCodeList.isEmpty()) {
            List<String> locationDescList = new ArrayList<>();
            for (String locationCode : locationCodeList) {
                String locationDesc = warehouseAreaLocationDOMapper.getLocationDesc(locationCode);
                locationDescList.add(locationDesc);
            }
            model.setLocationDesc(String.join(",", locationDescList));
        }
    }

    public void export(List<String> abnormalOutIds) throws Exception {
        List<AbnormalOutVO> voList = new ArrayList<>();
        for (String abnormalOutId : abnormalOutIds) {
            AbnormalOutDO entity = abnormalOutMapper.item(abnormalOutId);
            AbnormalOutVO model = new AbnormalOutVO();
            BeanUtils.copyProperties(entity, model);
            if (model != null) {
                voList.add(model);
            }
        }
        invokeExport(voList);
    }

    public void exportAll(AbnormalOutVO condition,String deptId) throws Exception {
        // 判断当前登陆的用户所属组织机构是否有配置仓库，如果开启了仓库控制并配置了仓库，则需要把配置的仓库加入到查询的限制条件
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(condition.getOrgId(), deptId);
        if(!wareHousePermission.isHasPermission()){
            invokeExport(Collections.EMPTY_LIST);
        }else {
            condition.setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }
        //PageHelperPlus.startPage(0, 0, "application_date desc");
        List<AbnormalOutExportDO> doList = abnormalOutMapper.selectExportList(condition);
//        for (AbnormalOutDO entity : doList) {
//            AbnormalOutVO model = new AbnormalOutVO();
//            BeanUtils.copyProperties(entity, model);
//            voList.add(model);
//        }
        invokeExportNew(doList);
    }

    private void invokeExport(List<AbnormalOutVO> voList) throws Exception {
        String title = "其它出库数据导出";
        String[] rowsName = new String[]{"序号", "申请单号", "sap预留单号", "零件凭证", "出库类型", "产生原因", "客户", "调出仓库", "制单人",
                "制单时间", "出库状态", "SAP同步状态", "SAP同步错误说明", "过账状态", "备注",
                "零件编码", "零件名称", "零件类型", "单位", "数量", "出库数量", "出库状态", "单价", "总价", "成本价", "出库金额", "储位", "保管员"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < voList.size(); i++) {
            AbnormalOutVO e = voList.get(i);
            List<AbnormalOutDetailDO> detailDOList = abnormalOutDetailMapper.exportListForLocationUser(e.getAbnormalNo());
            for (AbnormalOutDetailDO detailDO : detailDOList) {
                objs = new Object[rowsName.length];
                objs[0] = i + 1;
                objs[1] = e.getAbnormalNo();
                objs[2] = e.getSapOrder();
                objs[3] = e.getVoucherNo();
                objs[4] = e.getType();
                objs[5] = e.getReasonName();
                objs[6] = e.getAgentName();
                objs[7] = e.getOutLocation();
                objs[8] = e.getCreateName();
                objs[9] = sdf.format(e.getApplicationDate());
                objs[10] = getStatusDesc(e.getStatus());
                objs[11] = getSapStatusDesc(e.getIsSynsapSuccess());
                objs[12] = e.getSapErrorMsg();
                objs[13] = StringUtil.isNullOrEmpty(e.getVoucherNo()) ? "未过账" : "已过账";
                objs[14] = e.getNote();
                objs[15] = detailDO.getMaterialsNo();
                objs[16] = detailDO.getMaterialsDes();
                objs[17] = detailDO.getMaterialsType();
                objs[18] = detailDO.getUnit();
                objs[19] = detailDO.getQty();
                objs[20] = detailDO.getRealQty();
                objs[21] = getStatusDesc(detailDO.getStatus());
                objs[22] = DecimalUtil.roundDecimal4Output(detailDO.getPrice());
                objs[23] = DecimalUtil.roundDecimal4Output(detailDO.getTotalPrice());
                objs[24] = DecimalUtil.roundDecimal4Output(detailDO.getStandardPrice());
                objs[25] = DecimalUtil.roundDecimal4Output(DecimalUtil.mutiply(detailDO.getPrice(), detailDO.getRealQty()));
                objs[26] = detailDO.getStockLocation();
                objs[27] = detailDO.getStockUserName();
                dataList.add(objs);
            }

        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private void invokeExportNew(List<AbnormalOutExportDO> voList) throws Exception {
        String title = "其它出库数据导出";
        String[] rowsName = new String[]{"序号", "申请单号", "sap预留单号", "零件凭证", "出库类型", "产生原因", "客户", "调出仓库", "制单人",
                "制单时间", "出库状态", "SAP同步状态", "SAP同步错误说明", "过账状态", "备注",
                "零件编码", "零件名称", "零件类型", "单位", "数量", "出库数量", "出库状态", "单价", "总价", "成本价", "出库金额", "储位", "保管员"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < voList.size(); i++) {
            AbnormalOutExportDO e = voList.get(i);
            //List<AbnormalOutDetailDO> detailDOList = abnormalOutDetailMapper.exportListForLocationUser(e.getAbnormalNo());
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = e.getAbnormalNo();
            objs[2] = e.getSapOrder();
            objs[3] = e.getVoucherNo();
            objs[4] = e.getType();
            objs[5] = e.getReasonName();
            objs[6] = e.getAgentName();
            objs[7] = e.getOutLocation();
            objs[8] = e.getCreateName();
            objs[9] = sdf.format(e.getApplicationDate());
            objs[10] = getStatusDesc(e.getStatus());
            objs[11] = getSapStatusDesc(e.getIsSynsapSuccess());
            objs[12] = e.getSapErrorMsg();
            objs[13] = StringUtil.isNullOrEmpty(e.getVoucherNo()) ? "未过账" : "已过账";
            objs[14] = e.getNote();
            objs[15] = e.getMaterialsNo();
            objs[16] = e.getMaterialsDes();
            objs[17] = e.getMaterialsType();
            objs[18] = e.getUnit();
            objs[19] = e.getQty();
            objs[20] = e.getRealQty();
            objs[21] = getStatusDesc(e.getStatus());
            objs[22] = DecimalUtil.roundDecimal4Output(e.getPrice());
            objs[23] = DecimalUtil.roundDecimal4Output(e.getTotalPrice());
            objs[24] = DecimalUtil.roundDecimal4Output(e.getStandardPrice());
            objs[25] = DecimalUtil.roundDecimal4Output(DecimalUtil.mutiply(e.getPrice(), e.getRealQty()));
            objs[26] = e.getStockLocation();
            objs[27] = e.getStockUserName();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getStatusDesc(Integer statusId) {
        switch (statusId) {
            case 0:
            default:
                return "未出库";
            case 1:
                return "部分出库";
            case 2:
                return "已出库";
            case 3:
                return "强制结单";
        }

    }

    private String getSapStatusDesc(BigDecimal statusId) {
        if (statusId == null) {
            return "未同步";
        }
        switch (statusId.intValue()) {
            case 0:
            default:
                return "未同步";
            case 1:
                return "同步成功";
            case 2:
                return "同步失败";
        }
    }

//    //根据入库单更新非正常出库状态接口

    @Transactional(rollbackFor = Exception.class)
    public boolean updateByOut(String abnormalNo, String materialNo, BigDecimal realAmount,
                               String singleState, String totalState, String orgId, BigDecimal thisAmount, boolean updateReceipt) throws Exception {
        AbnormalOutDetailVO detailVO = new AbnormalOutDetailVO();
        detailVO.setAbnormalNo(abnormalNo);
        detailVO.setMaterialsNo(materialNo);
        detailVO.setOrgId(orgId);
        List<AbnormalOutDetailDO> list = abnormalOutDetailMapper.listAll(detailVO);
        if (ListUtil.isNullOrEmpty(list)) {
            return false;
        }
        AbnormalOutDetailDO detailDO = list.get(0);
        BigDecimal nowAmount = realAmount.subtract(detailDO.getRealQty() == null ? BigDecimal.ZERO : detailDO.getRealQty());
        detailDO.setRealQty(realAmount);
        detailDO.setStatus(Integer.valueOf(singleState));
        boolean success = abnormalOutDetailMapper.updateByPrimaryKeySelective(detailDO) > 0;
        if (success) {
            AbnormalOutVO outVO = new AbnormalOutVO();
            outVO.setAbnormalNo(abnormalNo);
            outVO.setOrgId(orgId);
            List<AbnormalOutDO> outList = list(outVO);
            if (ListUtil.isNullOrEmpty(outList)) {
                return false;
            }
            AbnormalOutDO outDO = outList.get(0);
            outDO.setStatus(Integer.valueOf(totalState));
            success = updateBy(outDO);

            if (success && thisAmount != null && !StringUtil.isNullOrEmpty(outDO.getSplitOrder())) {
                splitService.updateInOutNum(outDO.getSplitOrder(), materialNo, thisAmount, 2, orgId);
            }

            if (updateReceipt) {
                //更新发运交接单状态
                List<String> ids = deliveryReceiptLinkMapper.findReceiptIds(outDO.getId());
                if (!ListUtil.isNullOrEmpty(ids)) {
                    List<DeliveryReceiptMaterialDO> receiptMaterialDOList = deliveryReceiptMaterialMapper.listByIds(ids, materialNo);
                    if (!ListUtil.isNullOrEmpty(receiptMaterialDOList)) {
                        for (DeliveryReceiptMaterialDO receiptMaterialDO : receiptMaterialDOList) {
                            deliveryReceiptMaterialService.updateByOut(receiptMaterialDO, receiptMaterialDO.getOutQty().add(nowAmount));
                        }
                    }
                }

            }
        }
        return success;

    }

    public boolean updateBy(AbnormalOutDO abnormalOutDO) {
        return abnormalOutMapper.updateByPrimaryKeySelective(abnormalOutDO) > 0;
    }

    public List<AbnormalOutDO> list(AbnormalOutVO vo) {
        return abnormalOutMapper.list(vo);
    }

    /**
     * @Author: WangKe
     * @Description: 零件批量导入
     * @Date: 2018/3/1 0001
     */
    public FunctionResult importExcel(InputStream in, String warehouseCode, String areaCode, String orgId) throws Exception {
        FunctionResult result = new FunctionResult();
        HSSFWorkbook wb = new HSSFWorkbook(in);
        HSSFSheet sheet = wb.getSheetAt(0);

        int totalRow = sheet.getLastRowNum();
        if (totalRow < 2) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell = sheet.getRow(1).getLastCellNum();
        if (totalCell != 5) {
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<AbnormalOutDetailVO> detailVOList = new ArrayList<>();
        List<AbnormalOutDetailVO> errorDetailVOList = new ArrayList<>();
        MaterialLocationRelationVO relationVO = new MaterialLocationRelationVO();
        EnableAndOccupyVO enableAndOccupyVO;
        for (int i = 2; i <= totalRow; i++) {
            HSSFRow curRow = sheet.getRow(i);
            AbnormalOutDetailVO detailVO = new AbnormalOutDetailVO();
            if (curRow == null) {
                continue;
            }
            String no = getCellValue(curRow, 0);
            String materialsNo = getCellValue(curRow, 1);
            String qty = getCellValue(curRow, 4);
            if (StringUtil.isNullOrEmpty(no) && StringUtil.isNullOrEmpty(materialsNo) && StringUtil.isNullOrEmpty(qty)) {
                continue;
            }
            if (StringUtil.isNullOrEmpty(no)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("序号不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (StringUtil.isNullOrEmpty(materialsNo)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("零件编码不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (StringUtil.isNullOrEmpty(qty)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("出库数量不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (!isInteger(qty) || "0".equals(qty)) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("入库数量格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if (new BigDecimal(qty).compareTo(BigDecimal.valueOf(99999999.99)) > 0) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("入库数量过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            MaterialsVO materialsVO = materialsService.itemByNo(materialsNo, orgId);
            if (materialsVO == null) {
                detailVO.setErrorRow(i + 1);
                detailVO.setRemark("零件不存在");
                errorDetailVOList.add(detailVO);
                continue;
            }
            detailVO.setQty(new BigDecimal(qty));
            detailVO.setMaterialsNo(materialsVO.getMaterialsNo());
            detailVO.setMaterialsDes(materialsVO.getMaterialsDes());
            detailVO.setMaterialsType(materialsVO.getMaterialsType());
            detailVO.setUnit(materialsVO.getUnit());
            detailVO.setPrice(materialsVO.getPrice());
            detailVO.setCostPrice(materialsVO.getStandardPrice());
            detailVO.setCostSubtotal(detailVO.getCostPrice() == null ? new BigDecimal(0) : detailVO.getCostPrice()
                    .multiply(detailVO.getQty()));

            relationVO.setOrgId(orgId);
            relationVO.setMaterialNo(materialsVO.getMaterialsNo());
            relationVO.setWarehouseCode(warehouseCode);
            relationVO.setAreaCode(areaCode);
            detailVO.setLocationCode(materialLocationRelationMapper.findLocationCode(relationVO));
            enableAndOccupyVO = warehouseInventoryService.findEnableAndOccupyNum(detailVO.getMaterialsNo(), orgId, warehouseCode);
            BeanUtils.copyProperties(enableAndOccupyVO, detailVO);
            detailVOList.add(detailVO);
        }

        if (ListUtil.isNullOrEmpty(errorDetailVOList)) {
            result.setValue(ImportUtil.deRepeat(detailVOList, "MaterialsNo", "Qty", null, null));
            result.setCode(ErrorCode.Success);
        } else {
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
        return result;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    private String getCellValue(HSSFRow curRow, int i) {
        String value = "";
        if (curRow.getCell(i) != null) {
            curRow.getCell(i).setCellType(CellType.STRING);
            value = curRow.getCell(i).getStringCellValue();
        }
        return value;
    }

    /**
     * @Author: WangKe
     * @Description: 下载零件批量导入模板
     * @Date: 2018/3/1 0001
     */
    public void download() throws Exception {
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }

    /**
     * 手动完成单据<br>
     * materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态
     *
     * @param billNo      String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId       String 企业ID
     * @return ErrorCode 返回码
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manualFinish(String billNo, String materialsNo, String orgId) throws Exception {
        AbnormalOutDO abnormalOutDO = abnormalOutMapper.selectByAbnormalNo(billNo, orgId);
        if (StringUtil.isNullOrEmpty(materialsNo))//零件编码为空，更新单据状态为“手动完成”
        {
//            abnormalOutMapper.updateStatus(3,billNo);

            abnormalOutDO.setStatus(OUT_STATUS_FINISH);
            abnormalOutDO.setPostStatus(POST_STATUS_YES);
            abnormalOutMapper.updateByPrimaryKeySelective(abnormalOutDO);

            warehouseDeliveryService.updateState(billNo, 3, orgId);

            abnormalOutDetailMapper.updateStatus(3, billNo, materialsNo, orgId);
            warehouseDeliveryDetailMapper.updateAllStatus(3, billNo, orgId);
        } else {
            abnormalOutDetailMapper.updateStatus(3, billNo, materialsNo, orgId);
            warehouseDeliveryService.updateDetailState(billNo, materialsNo, null, 3, orgId);
            ErrorCode errorCode = checkBillFinished(billNo, orgId);

            if (ErrorCode.Success != errorCode) {
                throw new Exception("更新失败");
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 校验单据是否已完成<br>
     * 判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     *
     * @param billNo String
     * @param orgId  String
     * @return Boolean
     */
    private ErrorCode checkBillFinished(String billNo, String orgId) throws Exception {
        List<AbnormalOutDetailDO> detailDOs = abnormalOutDetailMapper.list(billNo);
        if (ListUtil.isNullOrEmpty(detailDOs)) {
            throw new Exception("未查询到其它出库单详情列表");
        }
        boolean manul = false;
        boolean flag = true;
        int status;
        for (AbnormalOutDetailDO temp : detailDOs) {
            if (temp.getStatus() == 3) {
                manul = true;
            }
            if (2 == temp.getStatus() || 3 == temp.getStatus()) {
                //完成状态
                continue;
            }
            flag = false;
        }

        if (flag) {
            if (manul) {
                status = 3;
            } else {
                status = 2;
            }
        } else {
            status = 1;
        }
        abnormalOutMapper.updateStatus(status, billNo);
        warehouseDeliveryService.updateState(billNo, status, orgId);
        return ErrorCode.Success;
    }

    public List<AbnormalOutDetailDO> getMaterialInfoByNo(List<String> billNoList){
        return abnormalOutDetailMapper.getMaterialInfoByNo(billNoList);
    }


    /**
     * @Des 查询当前机构未删除，已提交的待审核数据
     * @Date 2021/4/13 11:27
     * @Author wangzhaoyu
     * @Param [orgId]
     * @Return java.lang.Integer
     */
    public Integer countAuditData(String orgId) {
        Integer count = abnormalOutMapper.countAuditData(orgId);
        return count == null ? 0 : count;
    }
}
